package com.xbongbong.workflow.service.strategy.data.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.service.CustomerRuleService;
import com.xbongbong.paas.service.TransferBackRuleScriptService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.paas.util.WorkflowUtil;
import com.xbongbong.pro.businesstage.pojo.dto.ChangeStageDTO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.contractperformance.pojo.ContractPerformanceLogPojo;
import com.xbongbong.pro.customercommunicate.pojo.dto.CustomerDynamicAddDTO;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.message.constant.ContractPushConstant;
import com.xbongbong.pro.message.constant.OutstockPushConstant;
import com.xbongbong.pro.message.constant.PurchasePushConstant;
import com.xbongbong.pro.message.constant.QuotationPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.ConsistencySyncRabbitMqDTO;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.pro.opportunity.pojo.JudgeSaleStageSuccessPojo;
import com.xbongbong.pro.score.pojo.dto.DataScoreUpdateSingleDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.ContractUserEntity;
import com.xbongbong.saas.domain.entity.SmartReplenishmentEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.domain.entity.ext.QuotationEntityExt;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.RuleSettingEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.enums.dictionary.CustomerTypeEnum;
import com.xbongbong.saas.enums.dictionary.DictionaryEnum;
import com.xbongbong.saas.enums.dictionary.QuotationStatusEnum;
import com.xbongbong.saas.help.OpportunityStageLogHelp;
import com.xbongbong.saas.help.SaasHelp;
import com.xbongbong.saas.help.workflow.ContractPerformanceHelp;
import com.xbongbong.saas.help.workflow.MarketActivityForStaticHelp;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.ContractUserModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.DataDictionaryModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PurchaseBalanceModel;
import com.xbongbong.saas.model.QuotationModel;
import com.xbongbong.saas.model.SmartReplenishmentModel;
import com.xbongbong.saas.service.ConsistencySyncService;
import com.xbongbong.saas.service.CustomerCommunicateService;
import com.xbongbong.saas.service.DingRobotService;
import com.xbongbong.saas.service.ScoreCalculateService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.service.help.saas.ContractForPaymentHelp;
import com.xbongbong.workflow.service.help.saas.WorkFlowSaasStageHelp;
import com.xbongbong.workflow.service.strategy.data.AbstractWorkflowDataStrategy;
import com.xbongbong.workflow.service.strategy.data.WorkflowDataProcessStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 *
 * @author 魏荣杰
 *
 */
@Service
@Slf4j
public class WorkflowContractStrategy extends AbstractWorkflowDataStrategy implements WorkflowDataProcessStrategy {


    @Resource
    private CustomerModel customerModel;
    @Resource
    private DataDictionaryModel dataDictionaryModel;
    @Resource
    private QuotationModel quotationModel;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private UserModel userModel;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private ContractPerformanceHelp contractPerformanceHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private CustomerRuleService customerRuleService;
    @Resource
    private CustomerCommunicateService customerCommunicateService;
    @Resource
    private SaasHelp saasHelp;
    @Resource
    private ContractModel contractModel;
    @Resource
    private OpportunityStageLogHelp opportunityStageLogHelp;
    @Resource
    private ContractUserModel contractUserModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private ContractForPaymentHelp contractForPaymentHelp;
    @Resource
    private ScoreCalculateService scoreCalculateService;
    @Resource
    private MessageService messageService;
    @Resource
    private ConsistencySyncService consistencySyncService;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private DingRobotService dingRobotService;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private SmartReplenishmentModel smartReplenishmentModel;
    @Resource
    private PurchaseBalanceModel purchaseBalanceModel;
    @Resource
    private TransferBackRuleScriptService transferBackRuleScriptService;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private MarketActivityForStaticHelp marketActivityForStaticHelp;
    @Resource
    private WorkFlowSaasStageHelp workFlowSaasStageHelp;

    @Override
    public List<Integer> type() {
        return Collections.singletonList(XbbRefTypeEnum.CONTRACT.getCode());
    }

    @Override
    public void save(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {

        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);

        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long dataId = pojoData.getId();
        User user = workflowTransferPOJO.getUser();

        UserEntity userEntity = userModel.getByKeyIngoreDel(user.getUserId(), corpid);

        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(userEntity, userVO);

        Integer allOutbound = data.getInteger(ContractEnum.ALL_OUT_BOUND.getAttr());
        Long newCustomerId = FastJsonHelper.getLongFromFormData(data, ContractEnum.LINK_CUSTOMER.getAttr());
        Long newQuotationId = FastJsonHelper.eitherLongOrTheDefault(data, ContractEnum.QUOTATION_ID.getAttr(), 0L);
        Long oldQuotationId = FastJsonHelper.eitherLongOrTheDefault(data, ContractEnum.QUOTATION_ID.getAttr(), 0L);
        Long newOppId = FastJsonHelper.eitherLongOrTheDefault(data, ContractEnum.LINK_OPPORTUNITY.getAttr(), 0L);
        List<Long> newContactIds = FastJsonHelper.getTransferTypesFromData(data, ContractEnum.LINK_CONTACT.getAttr(), Long.class);
        try {
            // 更新合同业绩分配
            List<ContractPerformanceLogPojo> contractPerformanceLogList = new ArrayList<>();
            contractPerformanceHelp.changeContractPerformance(corpid, dataId, data, contractPerformanceLogList);
            if (CollectionsUtil.isNotEmpty(contractPerformanceLogList)) {
                // todo 添加日志

            }
        } catch (Exception e) {
            log.error("保存合同更新合同业绩分配", e);
        }
        try {
            if (Objects.nonNull(newCustomerId) && newCustomerId > 0) {
                // 更新客户状态和最后联系时间
                JSONObject jsonObject = new JSONObject();
                CustomerEntityExt customerEntityExt = customerModel.getByKey(newCustomerId, corpid);
                //新建合同订单，取其创建时间更新影响客户最后跟进时间
                Boolean flag = proFormHelp.getSingleRuleList(corpid, RuleSettingEnum.NEW_CONTRACT_ORDER_CREATE_TIME.getConfig(), customerEntityExt.getFormId());
                if (flag) {
                    jsonObject.put(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), DateTimeUtil.getInt());
                }

                Map<String, String> customerStatusMap = dataDictionaryModel.getDictionaryMap(DictionaryEnum.CUSTOMER_STATUS, corpid, null);
                if (customerStatusMap.containsKey(CustomerTypeEnum.TRANSACTION_CUSTOMER.getCode())) {
                    jsonObject.put(CustomerManagementEnum.TYPE.getAttr(), CustomerTypeEnum.TRANSACTION_CUSTOMER.getCode());
                }
                if ( !jsonObject.isEmpty() && jsonObject.size() > 0) {
                    UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(newCustomerId, jsonObject, corpid);
                    customerModel.updateBatch(Collections.singletonList(updateDataEntity), corpid);
                    //更新评分（合同信息变更，如果表单设置"更新规则"，可能修改客户的“最后更新时间”）
                    DataScoreUpdateSingleDTO dataScoreUpdateBatchDTO = new DataScoreUpdateSingleDTO();
                    dataScoreUpdateBatchDTO.setCorpid(corpid);
                    dataScoreUpdateBatchDTO.setUserId(workflowTransferPOJO.getUser().getUserId());
                    dataScoreUpdateBatchDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                    dataScoreUpdateBatchDTO.setDataId(updateDataEntity.getId());
                    dataScoreUpdateBatchDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
                    scoreCalculateService.updateSingle(dataScoreUpdateBatchDTO);
//                    scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,updateDataEntity.getId(),null);
                }
            }
        } catch (Exception e) {
            log.error("保存合同更新客户状态和最后联系时间", e);
        }

        try {
            if (Objects.nonNull(newCustomerId) && newCustomerId > 0) {
                Long signTime = data.getLong(ContractEnum.SIGN_TIME.getAttr());
                //编辑和新建合同都要更新客户的合同签订时间
                JSONObject jsonObject = new JSONObject();
                if (Objects.nonNull(signTime)) {
                    //获取最新签订时间一个合同
                    List<ContractEntityExt> list = contractModel.getLatestEntityListByCustomerId(corpid, newCustomerId);
                    if (CollectionsUtil.isNotEmpty(list)){
                        if (list.size() > 1){
                            ContractEntityExt latestContract = list.get(0);
                            ContractEntityExt secondContract = list.get(1);
                            Long latestSignDate = latestContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                            Long secondSignDate = secondContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                            if (Objects.equals(latestContract.getId(),dataId)){
                                //说明编辑的最近的这个合同
                                if (signTime >= latestSignDate){
                                    jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                                }else if(signTime > secondSignDate) {
                                    jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                                }else {
                                    jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), secondSignDate);
                                }
                            }else {
                                //说明编辑的其他合同
                                if (signTime > latestSignDate){
                                    jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                                }
                            }
                        }else {
                            ContractEntityExt latestContract = list.get(0);
                            Long latestSignDate = latestContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                            if (signTime >= latestSignDate){
                                jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                            }
                        }
                    }
                    if (!jsonObject.isEmpty()) {
                        customerModel.specialUpdate4SysDate(newCustomerId, jsonObject, corpid);
                    }
                }
            }
        } catch (Exception e) {
            log.error("保存合同更新客户的合同创建时间", e);
        }

        try {
            // 如果合同关联了报价单，那么需要将关联的报价单状态改为已生成合同
            boolean changeQuotationStatus = newQuotationId > 0;
            if (changeQuotationStatus) {
                PaasFormDataEntityExt quotationEntityExt = quotationModel.getByKey(newQuotationId, corpid);
                String oldStatus = FastJsonHelper.getStringOrDefaultFromFormData(quotationEntityExt.getData(), QuotationEnum.STATUS.getAttr(), "");
                String newStatus = QuotationStatusEnum.CREATED.getCode();
                if (!Objects.equals(oldStatus, newStatus)) {

                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(QuotationEnum.STATUS.getAttr(), newStatus);
                    UpdateDataEntity updateData = ExplainUtil.getUpdateData(newQuotationId, jsonObject, corpid);
                    quotationModel.updateBatch(Collections.singletonList(updateData), corpid);
                    newStatus = QuotationStatusEnum.CREATED.getName();
                    String name = FastJsonHelper.getStringOrDefaultFromFormData(quotationEntityExt.getData(), QuotationEnum.NAME.getAttr(), "");
                    QuotationEntityExt quotationEntity = new QuotationEntityExt();
                    BeanUtil.copyProperties(quotationEntityExt, quotationEntity);
                    List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.QUOTATION_STATUS_PUSH.getCode(), PushTypeEnum.QUOTATION_STATUS_PUSH.getSubCode(), userEntity, quotationEntity);
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(quotationEntityExt.getAppId(), quotationEntityExt.getMenuId(), quotationEntityExt.getFormId(), newQuotationId, Collections.singletonList(newQuotationId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.QUOTATION.getCode(), XbbRefTypeEnum.QUOTATION.getCode());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(newQuotationId), 0, null, I18nMessageUtil.getMessage(QuotationPushConstant.QUOTATAION_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(QuotationPushConstant.QUOTATAION_CHANGE_CONTENT), user.getName(), name, newStatus), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.QUOTATION_STATUS_PUSH);
                }
            }
        } catch (Exception e) {
            log.error("保存合同更新报价单状态", e);
        }

        try {
            boolean isLinkOpportunity = opportunityStageLogHelp.getIsLinkOpportunity(pojoData.getFormId(), corpid);
            // 如果合同关联了机会，而且机会没有阶段或者机会有关联阶段但是不是成功阶段，那么需要将关联的机会阶段变为成功阶段
            if (newOppId > 0 && isLinkOpportunity) {
                JudgeSaleStageSuccessPojo judgeSaleStageSuccessPojo = opportunityStageLogHelp.judgeSaleStageSuccessWhenContract(corpid, newOppId);
                if (judgeSaleStageSuccessPojo.getNeedChangeStage()) {
                    ChangeStageDTO changeStageDTO = new ChangeStageDTO();
                    changeStageDTO.setUserId(user.getUserId());
                    changeStageDTO.setCorpid(corpid);
                    changeStageDTO.setLoginUser(userVO);
                    changeStageDTO.setOpportunity(judgeSaleStageSuccessPojo.getOpportunity());
                    changeStageDTO.setTargetStage(judgeSaleStageSuccessPojo.getTargetStage());
                    changeStageDTO.setDataId(newOppId);
                    changeStageDTO.setBusinessType(XbbRefTypeEnum.SALE_STAGE.getCode());
                    changeStageDTO.setNextCode(judgeSaleStageSuccessPojo.getTargetStage().getCode());
                    changeStageDTO.setFastUpdate(true);
                    changeStageDTO.setSourceStage(judgeSaleStageSuccessPojo.getSourceStage());
                    opportunityStageLogHelp.changeStage(changeStageDTO);
                }
            }
        } catch (Exception e) {
            log.error("保存合同更新关联机会的阶段为赢单", e);
        }

        try {
            CustomerEntityExt customerEntity = customerModel.getByKey(dataId, corpid);
            Long customerFormId  = customerEntity != null ? customerEntity.getFormId() : 0L;
            // 去除客户标签
                if (commonHelp.isCustomerPublicPoolSeniorModel(corpid)){
                    transferBackRuleScriptService.deletePublicSeniorTag(corpid, Collections.singletonList(dataId), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), customerFormId);
                }else {
                    customerRuleService.deletePublicTag(corpid, Collections.singletonList(dataId));

                }
            } catch (Exception e) {
            log.error("保存合同去除关联客户标签", e);
        }

        boolean notDistributeBusinessType = isNotDistributeBusinessType(workflowTransferPOJO);
        //创建信息
        //是否关联报价单
        try{
            String quotationId = data.getString(ContractEnum.QUOTATION_ID.getAttr());
            if (quotationId != null) {
                //新建合同关联报价单
                String status = QuotationStatusEnum.CREATED.getName();
                status = "\"" + status + "\"";
                String contractName = data.getString(ContractEnum.NAME.getAttr());
                contractName = contractName == null ? "" : ": " + contractName;
                String communicateMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.ADD_CONTRACT_RELATED_QUOTATION), user.getName()+" ", status) + contractName;
                Integer subType = ProjectLogEnum.CONTRACT_QUOTATION.getSubType();
                String log = I18nMessageUtil.getMessage(I18nStringConstant.CONTRACT_RELATED_QUOTATION_LOG);

                CustomerDynamicAddDTO customerDynamicAddDTO = new CustomerDynamicAddDTO();
                String customerName = data.getString(ContractEnum.LINK_CUSTOMER_HIDE.getAttr());
                customerDynamicAddDTO.setCorpid(corpid);
                customerDynamicAddDTO.setUserId(user.getUserId());
                customerDynamicAddDTO.setContractIds(Collections.singletonList(dataId));
                customerDynamicAddDTO.setCustomerName(customerName);
                customerDynamicAddDTO.setMemo(communicateMemo);
                customerDynamicAddDTO.setCommunicateBusinessText(data.getString(BasicConstant.SERIAL_NO));
                customerDynamicAddDTO.setCommunicateBusinessType(XbbRefTypeEnum.CONTRACT.getCode());
                customerDynamicAddDTO.setDataId(dataId);
                customerDynamicAddDTO.setLogType(subType);
                customerDynamicAddDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());

                if (!notDistributeBusinessType) {
                    customerDynamicAddDTO.setCustomerId(newCustomerId);
                    customerDynamicAddDTO.setDistributorMark(DistributorMarkEnum.DISTRIBUTOR.getCode());
                }

                customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);

            }
        }catch(Exception e){
            log.error("创建信息关联报价单", e);
        }
        try {
            //新建合同
            if(notDistributeBusinessType) {
                String memo = Objects.equals(workflowTransferPOJO.getIsImport(), 1) ? CrmLogMemoConstant.DYNAMIC_USER_IMPORT : CrmLogMemoConstant.DYNAMIC_USER_ADD;
                PaasFormEntity paasForm = proFormHelp.getPaasForm(pojoData.getFormId(), pojoData.getBusinessType(), corpid);
                String paasFormName = I18nMessageUtil.getMessage(CommonConstant.CONTRACT);
                if (Objects.nonNull(paasForm)) {
                    paasFormName = paasForm.getName();
                }
                String communicateMemo = String.format(I18nMessageUtil.getMessage(memo), user.getName(), paasFormName, data.getString(BasicConstant.SERIAL_NO));
                Integer subType = ProjectLogEnum.CONTRACT_CREATE.getSubType();
                // String logStr = I18nMessageUtil.getMessage(I18nStringConstant.CONTRACT_CREATE_LOG);
                CustomerDynamicAddDTO customerDynamicAddDTO = new CustomerDynamicAddDTO();
                String customerName = data.getString(ContractEnum.LINK_CUSTOMER_HIDE.getAttr());
                customerDynamicAddDTO.setCorpid(corpid);
                customerDynamicAddDTO.setUserId(user.getUserId());
                customerDynamicAddDTO.setCustomerId(newCustomerId);
                customerDynamicAddDTO.setContactIds(newContactIds);
                if (newOppId != 0L) {
                    customerDynamicAddDTO.setOpportunityIds(Collections.singletonList(newOppId));
                }
                customerDynamicAddDTO.setCustomerName(customerName);
                customerDynamicAddDTO.setContractIds(Collections.singletonList(dataId));
                customerDynamicAddDTO.setMemo(communicateMemo);
                customerDynamicAddDTO.setCommunicateBusinessText(data.getString(BasicConstant.SERIAL_NO));
                customerDynamicAddDTO.setCommunicateBusinessType(XbbRefTypeEnum.CONTRACT.getCode());
                customerDynamicAddDTO.setDataId(dataId);
                customerDynamicAddDTO.setLogType(subType);
                customerDynamicAddDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());

                customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
            }else {
                //新建合同
                String operate = Objects.equals(workflowTransferPOJO.getIsImport(), BasicConstant.ONE) ? I18nMessageUtil.getMessage(I18nStringConstant.IMPORTED) : I18nMessageUtil.getMessage(I18nStringConstant.ADD);
                String communicateMemo = user.getName() + operate + I18nMessageUtil.getMessage(CommonConstant.CONTRACT) + " :" + data.getString(BasicConstant.SERIAL_NO);
                Integer subType = ProjectLogEnum.CONTRACT_CREATE.getSubType();
                // String logStr = I18nMessageUtil.getMessage(I18nStringConstant.CONTRACT_CREATE_LOG);
                CustomerDynamicAddDTO customerDynamicAddDTO = new CustomerDynamicAddDTO();
                String customerName = data.getString(ContractEnum.LINK_CUSTOMER_HIDE.getAttr());
                customerDynamicAddDTO.setCorpid(corpid);
                customerDynamicAddDTO.setUserId(user.getUserId());
                customerDynamicAddDTO.setCustomerId(newCustomerId);
                customerDynamicAddDTO.setCustomerName(customerName);
                customerDynamicAddDTO.setMemo(communicateMemo);
                customerDynamicAddDTO.setCommunicateBusinessText(data.getString(BasicConstant.SERIAL_NO));
                customerDynamicAddDTO.setCommunicateBusinessType(XbbRefTypeEnum.CONTRACT.getCode());
                customerDynamicAddDTO.setDataId(dataId);
                customerDynamicAddDTO.setLogType(subType);
                customerDynamicAddDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
                customerDynamicAddDTO.setDistributorMark(DistributorMarkEnum.DISTRIBUTOR.getCode());
                customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
            }
        } catch (Exception e) {
            log.error("工作流新建合同动态失败", e);
        }

        try {
            if (!Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
                // 合同创建消息推送
                ContractEntityExt contractEntityExt = new ContractEntityExt();
                contractEntityExt.setId(dataId);
                contractEntityExt.setData(data);
                List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CONTRACT_ADD_PUSH.getCode(), PushTypeEnum.CONTRACT_ADD_PUSH.getSubCode(), userEntity, contractEntityExt);
                PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), pojoData.getBusinessType(), pojoData.getSubBusinessType());
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(ContractPushConstant.CONTRACT_ADD_TITLE), String.format(I18nMessageUtil.getMessage(ContractPushConstant.CONTRACT_ADD_CONTENT), userEntity.getName(), data.getString(BasicConstant.SERIAL_NO)), null, options);
                messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.CONTRACT_ADD_PUSH);
            }
        } catch (Exception e) {
            log.error("合同创建消息推送", e);
        }


        if (!Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
            try {
                // 合同创建成功时未出库产品的待出库消息推送
                if (Objects.equals(allOutbound, 0)) {
                    //推送给仓库主管 系统默认的仓库主管的roleId=22?
                    List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(22));
                    List<String> userIdList = new ArrayList<>();
                    for (UserEntity manager : managers) {
                        userIdList.add(manager.getUserId());
                    }
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTRACT.getCode(), XbbRefTypeEnum.CONTRACT.getCode());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(OutstockPushConstant.OUTSTOCK_TITLE), String.format(I18nMessageUtil.getMessage(OutstockPushConstant.WAIT_OUTSTOCK_CONTENT), data.getString(BasicConstant.SERIAL_NO)), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.WAIT_OUTSTOCK_PUSH);
                }
            } catch (Exception e) {
                log.error("合同创建成功时未出库产品的待出库消息推送", e);
            }


            try {
                List<ContractProductEntity> contractProductEntityList = saasHelp.getContractProductWaitOutStock(corpid, Collections.singletonList(dataId));
                JSONArray lackProductArray = saasHelp.getWaitPurchaseInfo(corpid, contractProductEntityList);
                // 合同创建成功时缺货产品的待采购消息推送
                if (Objects.equals(allOutbound, 0)) {
                    if (!lackProductArray.isEmpty()) {
                        // 推送给采购主管 系统默认的采购主管的roleId=21?
                        List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(21));
                        List<String> userIdList = new ArrayList<>();
                        for (UserEntity manager : managers) {
                            userIdList.add(manager.getUserId());
                        }
                        PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTRACT.getCode(), pojoData.getSubBusinessType());
                        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(PurchasePushConstant.PURCHASE_TITLE), String.format(I18nMessageUtil.getMessage(PurchasePushConstant.WAIT_PURCHASE_CONTENT), data.getString(BasicConstant.SERIAL_NO)), null, options);
                        messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.WAIT_PURCHASE_PUSH);
                    }
                }
            } catch (Exception e) {
                log.error("合同创建成功时缺货产品的待采购消息推送", e);
            }

        }

        try {
            // 保存回款
            contractForPaymentHelp.savePayment(workflowTransferPOJO, saasNeedRedundantAttrPojo);
            contractForPaymentHelp.savePaymentSheet(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } catch (Exception e) {
            log.error("保存合同时保存回款", e);
        }
        addLinkDataDynamic(workflowTransferPOJO);
        // api
        apiHook(workflowTransferPOJO);
        // 发送钉钉群消息
        PaasFormDataEntity paasFormDataEntity = WorkflowUtil.getFormData(workflowTransferPOJO);
        String signer = paasFormDataEntity.getData().getString(ContractEnum.SIGN_PERSON.getAttr());
        String signName = paasFormDataEntity.getData().getString(ContractEnum.SIGN_NAME.getAttr());
        Runnable sendRobotRunnable = () -> {
            try {
                dingRobotService.sendRobotByBusinessType(corpid, signer, signName, paasFormDataEntity, XbbRefTypeEnum.CONTRACT);
            } catch (Exception e) {
                log.error("发送群消息出错", e);
            }
        };
        threadPoolBeanConfig.sendRobotMsgThreadPool().execute(sendRobotRunnable);

        marketActivityForStaticHelp.addMarketActivity(paasFormDataEntity, XbbRefTypeEnum.CONTRACT);

        //阶段处理
        workFlowSaasStageHelp.afterSaveStage(workflowTransferPOJO);
        // log
        afterSaveLog(workflowTransferPOJO);

    }

    @Override
    public void update(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {

        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);


        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long dataId = pojoData.getId();
        User user = workflowTransferPOJO.getUser();
        UserEntity userEntity = userModel.getByKeyIngoreDel(user.getUserId(), corpid);

        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(userEntity, userVO);


        JSONObject oldData = workflowTransferPOJO.getOldData().getData();
        Integer allOutbound = data.getInteger(ContractEnum.ALL_OUT_BOUND.getAttr());
        Long newCustomerId = FastJsonHelper.getLongFromFormData(data, ContractEnum.LINK_CUSTOMER.getAttr());
        Long newQuotationId = FastJsonHelper.eitherLongOrTheDefault(data, ContractEnum.QUOTATION_ID.getAttr(), 0L);
        Long oldQuotationId = FastJsonHelper.eitherLongOrTheDefault(oldData, ContractEnum.QUOTATION_ID.getAttr(), 0L);

        Long newOppId = FastJsonHelper.eitherLongOrTheDefault(data, ContractEnum.LINK_OPPORTUNITY.getAttr(), 0L);
        Long oldOppId = FastJsonHelper.eitherLongOrTheDefault(oldData, ContractEnum.LINK_OPPORTUNITY.getAttr(), 0L);

        try {
            // 更新合同业绩分配
            List<ContractPerformanceLogPojo> contractPerformanceLogList = new ArrayList<>();
            contractPerformanceHelp.changeContractPerformance(corpid, dataId, data, contractPerformanceLogList);
            if (CollectionsUtil.isNotEmpty(contractPerformanceLogList)) {
                // todo 添加日志

            }
        } catch (Exception e) {
            log.error("保存合同更新合同业绩分配", e);
        }

        try {
            if (Objects.nonNull(newCustomerId) && newCustomerId > 0) {
                // 更新客户状态和最后联系时间
                JSONObject jsonObject = new JSONObject();
                CustomerEntityExt customerEntityExt = customerModel.getByKey(newCustomerId, corpid);
                //新建合同订单，取其创建时间更新影响客户最后跟进时间
                Boolean flag = proFormHelp.getSingleRuleList(corpid, RuleSettingEnum.NEW_CONTRACT_ORDER_CREATE_TIME.getConfig(), customerEntityExt.getFormId());
                if (flag) {
                    jsonObject.put(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), DateTimeUtil.getInt());
                }

                Map<String, String> customerStatusMap = dataDictionaryModel.getDictionaryMap(DictionaryEnum.CUSTOMER_STATUS, corpid, null);
                if (customerStatusMap.containsKey(CustomerTypeEnum.TRANSACTION_CUSTOMER.getCode())) {
                    jsonObject.put(CustomerManagementEnum.TYPE.getAttr(), CustomerTypeEnum.TRANSACTION_CUSTOMER.getCode());
                }
                if ( !jsonObject.isEmpty() && jsonObject.size() > 0) {
                    UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(newCustomerId, jsonObject, corpid);
                    customerModel.updateBatch(Collections.singletonList(updateDataEntity), corpid);
                    //更新评分（合同信息变更，如果表单设置"更新规则"，可能修改客户的“最后更新时间”）
                    DataScoreUpdateSingleDTO dataScoreUpdateBatchDTO = new DataScoreUpdateSingleDTO();
                    dataScoreUpdateBatchDTO.setCorpid(corpid);
                    dataScoreUpdateBatchDTO.setUserId(workflowTransferPOJO.getUser().getUserId());
                    dataScoreUpdateBatchDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                    dataScoreUpdateBatchDTO.setDataId(updateDataEntity.getId());
                    dataScoreUpdateBatchDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
                    scoreCalculateService.updateSingle(dataScoreUpdateBatchDTO);
//                    scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,updateDataEntity.getId(),null);
                }
            }
        } catch (Exception e) {
            log.error("保存合同更新客户状态和最后联系时间", e);
        }

        try {
            if (Objects.nonNull(newCustomerId) && newCustomerId > 0) {
                Long signTime = data.getLong(ContractEnum.SIGN_TIME.getAttr());
                //编辑和新建合同都要更新客户的合同签订时间
                JSONObject jsonObject = new JSONObject();
                if (Objects.nonNull(signTime)) {
                    //获取最新签订时间一个合同
                    List<ContractEntityExt> list = contractModel.getLatestEntityListByCustomerId(corpid, newCustomerId);
                    if (CollectionsUtil.isNotEmpty(list)){
                        if (list.size() > 1){
                            ContractEntityExt latestContract = list.get(0);
                            ContractEntityExt secondContract = list.get(1);
                            Long latestSignDate = latestContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                            Long secondSignDate = secondContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                            if (Objects.equals(latestContract.getId(),dataId)){
                                //说明编辑的最近的这个合同
                                if (signTime >= latestSignDate){
                                    jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                                }else if(signTime > secondSignDate) {
                                    jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                                }else {
                                    jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), secondSignDate);
                                }
                            }else {
                                //说明编辑的其他合同
                                if (signTime > latestSignDate){
                                    jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                                }
                            }
                        }else {
                            ContractEntityExt latestContract = list.get(0);
                            Long latestSignDate = latestContract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                            if (signTime >= latestSignDate){
                                jsonObject.put(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr(), signTime);
                            }
                        }
                    }
                    if (!jsonObject.isEmpty()) {
                        customerModel.specialUpdate4SysDate(newCustomerId, jsonObject, corpid);
                    }
                }
            }
        } catch (Exception e) {
            log.error("保存合同更新客户的合同创建时间", e);
        }


        try {
            // 如果合同关联了报价单，那么需要将关联的报价单状态改为已生成合同
            boolean changeQuotationStatus = !Objects.equals(newQuotationId, oldQuotationId) && (newQuotationId > 0);
            if (changeQuotationStatus) {
                PaasFormDataEntityExt quotationEntityExt = quotationModel.getByKey(newQuotationId, corpid);
                String oldStatus = FastJsonHelper.getStringOrDefaultFromFormData(quotationEntityExt.getData(), QuotationEnum.STATUS.getAttr(), "");
                String newStatus = QuotationStatusEnum.CREATED.getCode();
                if (!Objects.equals(oldStatus, newStatus)) {

                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(QuotationEnum.STATUS.getAttr(), newStatus);
                    UpdateDataEntity updateData = ExplainUtil.getUpdateData(newQuotationId, jsonObject, corpid);
                    quotationModel.updateBatch(Collections.singletonList(updateData), corpid);
                    newStatus = QuotationStatusEnum.CREATED.getName();
                    String name = FastJsonHelper.getStringOrDefaultFromFormData(quotationEntityExt.getData(), QuotationEnum.NAME.getAttr(), "");
                    QuotationEntityExt quotationEntity = new QuotationEntityExt();
                    BeanUtil.copyProperties(quotationEntityExt, quotationEntity);
                    List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.QUOTATION_STATUS_PUSH.getCode(), PushTypeEnum.QUOTATION_STATUS_PUSH.getSubCode(), userEntity, quotationEntity);
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(quotationEntityExt.getAppId(), quotationEntityExt.getMenuId(), quotationEntityExt.getFormId(), newQuotationId, Collections.singletonList(newQuotationId), SaasMarkEnum.SAAS.getCode(), pojoData.getBusinessType(), pojoData.getSubBusinessType());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(newQuotationId), 0, null, I18nMessageUtil.getMessage(QuotationPushConstant.QUOTATAION_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(QuotationPushConstant.QUOTATAION_CHANGE_CONTENT), userEntity.getName(), name, newStatus), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.QUOTATION_STATUS_PUSH);
                }
            }
        } catch (Exception e) {
            log.error("保存合同更新报价单状态", e);
        }

        try {
            // 如果合同关联了机会，而且机会没有阶段或者机会有关联阶段但是不是成功阶段，那么需要将关联的机会阶段变为成功阶段
            if (!Objects.equals(newOppId, oldOppId) && (newOppId > 0)) {
                JudgeSaleStageSuccessPojo judgeSaleStageSuccessPojo = opportunityStageLogHelp.judgeSaleStageSuccessWhenContract(corpid, newOppId);
                if (judgeSaleStageSuccessPojo.getNeedChangeStage()) {
                    ChangeStageDTO changeStageDTO = new ChangeStageDTO();
                    changeStageDTO.setUserId(user.getUserId());
                    changeStageDTO.setCorpid(corpid);
                    changeStageDTO.setLoginUser(userVO);
                    changeStageDTO.setOpportunity(judgeSaleStageSuccessPojo.getOpportunity());
                    changeStageDTO.setTargetStage(judgeSaleStageSuccessPojo.getTargetStage());
                    changeStageDTO.setDataId(newOppId);
                    changeStageDTO.setBusinessType(XbbRefTypeEnum.SALE_STAGE.getCode());
                    changeStageDTO.setNextCode(judgeSaleStageSuccessPojo.getTargetStage().getCode());
                    changeStageDTO.setFastUpdate(true);
                    changeStageDTO.setSourceStage(judgeSaleStageSuccessPojo.getSourceStage());
                    opportunityStageLogHelp.changeStage(changeStageDTO);
                }
            }
        } catch (Exception e) {
            log.error("保存合同更新关联机会的阶段为赢单", e);
        }

        try {
            // 去除客户标签
            CustomerEntityExt customerEntity = customerModel.getByKey(dataId, corpid);
            Long customerFormId = customerEntity != null ? customerEntity.getFormId() : 0L;
            if (commonHelp.isCustomerPublicPoolSeniorModel(corpid)) {
                transferBackRuleScriptService.deletePublicSeniorTag(corpid, Collections.singletonList(dataId), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), customerFormId);
            } else{
                customerRuleService.deletePublicTag(corpid, Collections.singletonList(dataId));
            }
        } catch (Exception e) {
            log.error("保存合同去除关联客户标签", e);
        }


        try {
            if (!Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
                // fix:53021 修改合同状态进入审批后，消息推送内容不再包含审批人对合同状态修改结果
                WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(workflowTransferPOJO.getBackupDataId(), corpid);
                JSONObject backupData = workflowBackupDataEntity.getData();
                // 合同状态变更消息推送
                if (!Objects.equals(backupData.getString(ContractEnum.STATUS.getAttr()), data.getString(ContractEnum.STATUS.getAttr()))) {
                    String oldStatus = dataDictionaryModel.getDictionaryValue(corpid, DictionaryEnum.CONTRACT_STATUS, backupData.getInteger(ContractEnum.STATUS.getAttr()));
                    String newStatus = dataDictionaryModel.getDictionaryValue(corpid, DictionaryEnum.CONTRACT_STATUS, data.getInteger(ContractEnum.STATUS.getAttr()));
                    ContractEntityExt contractEntityExt = new ContractEntityExt();
                    contractEntityExt.setId(dataId);
                    contractEntityExt.setData(data);
                    List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CONTRACT_CHANGE_PUSH.getCode(), PushTypeEnum.CONTRACT_CHANGE_PUSH.getSubCode(), userEntity, contractEntityExt);
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(workflowBackupDataEntity.getAppId(), workflowBackupDataEntity.getMenuId(), workflowBackupDataEntity.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), pojoData.getBusinessType(), pojoData.getSubBusinessType());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(ContractPushConstant.CONTRACT_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(ContractPushConstant.CONTRACT_CHANGE_CONTENT), userEntity.getName(), oldStatus, newStatus), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.CONTRACT_CHANGE_PUSH);
                }
            }
        } catch (Exception e) {
            log.error("合同保存时合同状态变更消息推送，backupId="+ workflowTransferPOJO.getBackupDataId()+"；corpid="+corpid +"；taskId="+workflowTransferPOJO.getTaskId(), e);
        }

        if (!Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
            try {
                // 合同创建成功时未出库产品的待出库消息推送
                if (Objects.equals(allOutbound, 0)) {
                    //推送给仓库主管 系统默认的仓库主管的roleId=22?
                    List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(22));
                    List<String> userIdList = new ArrayList<>();
                    for (UserEntity manager : managers) {
                        userIdList.add(manager.getUserId());
                    }
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTRACT.getCode(), XbbRefTypeEnum.CONTRACT.getCode());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(OutstockPushConstant.OUTSTOCK_TITLE), String.format(I18nMessageUtil.getMessage(OutstockPushConstant.WAIT_OUTSTOCK_CONTENT), data.getString(BasicConstant.SERIAL_NO)), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.WAIT_OUTSTOCK_PUSH);
                }
            } catch (Exception e) {
                log.error("合同创建成功时未出库产品的待出库消息推送", e);
            }


            try {
                List<ContractProductEntity> contractProductEntityList = saasHelp.getContractProductWaitOutStock(corpid, Collections.singletonList(dataId));
                JSONArray lackProductArray = saasHelp.getWaitPurchaseInfo(corpid, contractProductEntityList);
                // 合同创建成功时缺货产品的待采购消息推送
                if (Objects.equals(allOutbound, 0)) {
                    if (!lackProductArray.isEmpty()) {
                        // 推送给采购主管 系统默认的采购主管的roleId=21?
                        List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(21));
                        List<String> userIdList = new ArrayList<>();
                        for (UserEntity manager : managers) {
                            userIdList.add(manager.getUserId());
                        }
                        PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), pojoData.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTRACT.getCode(), pojoData.getBusinessType());
                        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(PurchasePushConstant.PURCHASE_TITLE), String.format(I18nMessageUtil.getMessage(PurchasePushConstant.WAIT_PURCHASE_CONTENT), data.getString(BasicConstant.SERIAL_NO)), null, options);
                        messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.WAIT_PURCHASE_PUSH);
                    }
                }
            } catch (Exception e) {
                log.error("合同创建成功时缺货产品的待采购消息推送", e);
            }

        }

        try {
            contractForPaymentHelp.updatePayment(workflowTransferPOJO, saasNeedRedundantAttrPojo);
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.help.saas.ContractForPaymentHelp.updatePayment", e);
        }

        try{
            String newContractSerialNo = data.getString(BasicConstant.SERIAL_NO);
            String oldContractSerialNo = oldData.getString(BasicConstant.SERIAL_NO);
            if (!Objects.equals(oldContractSerialNo, newContractSerialNo)) {
                ConsistencySyncRabbitMqDTO consistencySyncRabbitMqDTO = new ConsistencySyncRabbitMqDTO(corpid, dataId, newContractSerialNo, newContractSerialNo);
                consistencySyncService.syncContract(consistencySyncRabbitMqDTO);
            }
        }catch (Exception e){
            log.error("数据一致性同步", e);
        }
        PaasFormDataEntity paasFormDataEntity = WorkflowUtil.getFormData(workflowTransferPOJO);
        marketActivityForStaticHelp.updateMarketActivity(paasFormDataEntity, RedundantTemplateTypeEnum.CONTRACT);

        try {
            if(isNotDistributeBusinessType(workflowTransferPOJO)) {
                PaasFormEntity paasForm = proFormHelp.getPaasForm(pojoData.getFormId(), pojoData.getBusinessType(), corpid);
                String paasFormName = XbbRefTypeEnum.CONTRACT.getName();
                if (Objects.nonNull(paasForm)) {
                    paasFormName = paasForm.getName();
                }
                String creatorUserName = Objects.isNull(userEntity) ? "" : userEntity.getName();
                String communicateMemo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.DYNAMIC_USER_UPDATE_BASE_INFO), creatorUserName, paasFormName);
                CustomerDynamicAddDTO customerDynamicAddDTO = new CustomerDynamicAddDTO();
                customerDynamicAddDTO.setCorpid(corpid);
                customerDynamicAddDTO.setUserId(user.getUserId());
                customerDynamicAddDTO.setMemo(communicateMemo);
                customerDynamicAddDTO.setContractIds(Collections.singletonList(dataId));
                customerDynamicAddDTO.setDataId(0L);
                customerDynamicAddDTO.setCommunicateBusinessType(null);
                customerDynamicAddDTO.setCommunicateBusinessText("");
                customerDynamicAddDTO.setLogType(ProjectLogEnum.CONTRACT_UPDATE.getSubType());
                customerDynamicAddDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
                customerCommunicateService.addCustomerDynamic(customerDynamicAddDTO);
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowContractStrategy.update", e);
        }

        //阶段处理
        workFlowSaasStageHelp.afterSaveStage(workflowTransferPOJO);
        // api
        apiHook(workflowTransferPOJO);
        // log
        afterUpdateLog(workflowTransferPOJO);
    }

    @Override
    public void updateBack(Long taskId, WorkflowTransferPOJO workflowTransferPOJO) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Long backupDataId = workflowTransferPOJO.getBackupDataId();
            Long dataId = workflowTransferPOJO.getData().getId();
            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(backupDataId, corpid);
            if (Objects.nonNull(workflowBackupDataEntity)) {
                JSONObject data = workflowBackupDataEntity.getData();

                replenishAttrForBackupData(workflowTransferPOJO.getData().getData(), data);

                ContractEntityExt contractEntityExt = new ContractEntityExt();
                contractEntityExt.setId(dataId);
                contractEntityExt.setCorpid(corpid);
                contractEntityExt.setData(data);
                contractEntityExt.setSerialNo(data.getString(FieldTypeEnum.SERIALNO.getAlias()));
                // 获取负责人
                contractEntityExt.setOwnerId(getOwnerId(data));
                contractEntityExt.setDepartmentId(data.getLong(FieldTypeEnum.DEPARTMENTID.getAlias()));
                List<ContractProductEntity> list = JSON.parseArray(data.getString(StringConstant.PRODUCT), ContractProductEntity.class);
                List<ContractUserEntity> contractUserList = JSON.parseArray(data.getString(StringConstant.USER_TEAM), ContractUserEntity.class);

                FormDataUtil.removeSystemData(data);
                data.remove(StringConstant.USER_TEAM);
                data.remove(StringConstant.PRODUCT);
                if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
                    contractEntityExt.setFlowStatus(FlowStatusEnum.PASS.getType());
                }
                contractModel.update(contractEntityExt);
                // 回退被删掉的子表单
                updateBackSubForm(contractEntityExt, corpid, IndexTypeEnum.IDX_SAAS_CONTRACT_SUB);
                //回退被删掉的富文本
                updateBackRichText(taskId, workflowTransferPOJO);

                saveUserTeam(contractUserList, corpid, contractEntityExt.getId());
                saveProduct(list, corpid, contractEntityExt.getId());
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowContractStrategy.updateBack error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void approvalFailed(Long taskId, WorkflowTransferPOJO workflowTransferPOJO, Integer taskType) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Data workflowData = workflowTransferPOJO.getData();
            Long dataId = workflowData.getId();
            Long formId = workflowData.getFormId();
            Integer businessType = workflowData.getBusinessType();
            Integer saasMark = workflowData.getSaasMark();
            ContractEntityExt contractEntityExt = new ContractEntityExt();
            contractEntityExt.setId(dataId);
            if (Objects.equals(TaskTypeEnum.REVOKE.getType(), taskType)) {
                contractEntityExt.setFlowStatus(FlowStatusEnum.REVOKE.getType());
            } else {
                contractEntityExt.setFlowStatus(FlowStatusEnum.REJECT.getType());
            }
            contractEntityExt.setCorpid(corpid);
            contractEntityExt.setUpdateTime(DateTimeUtil.getInt());
            contractModel.update(contractEntityExt);
            // 子表单
            DelEnum del = DelEnum.APPROVE_FAILED;

            paasFormSubDataModel.deleteBatchByDataId(Collections.singletonList(dataId), corpid, IndexTypeEnum.IDX_SAAS_CONTRACT_SUB, del);
            //富文本
            deleteFormRichText(dataId, corpid, formId, businessType, saasMark, DelEnum.NORMAL);
            // 关联产品
            List<ContractProductEntity> productList = contractProductModel.getProductsByConId(dataId, corpid);
            if (CollectionsUtil.isNotEmpty(productList)) {
                contractProductModel.deleteBatch(productList, corpid, del.getDel());
                addRollBackSmartData(corpid,productList);
            }
            // 团队
            List<ContractUserEntity> contractUserList = contractUserModel.getContractUserList(corpid, dataId, null);
            if (CollectionsUtil.isNotEmpty(contractUserList)) {
                contractUserModel.deleteBatchUser(contractUserList, corpid, del.getDel());
            }

        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowContractStrategy.approvalFailed error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private void saveProduct(List<ContractProductEntity> list, String corpid, Long dataId) throws XbbException {
        try {
            List<ContractProductEntity> productList = contractProductModel.getProductsByConId(dataId, corpid);

            // 遍历备份表中的产品
            List<Long> backupProductId = new ArrayList<>();
            list.forEach(item->backupProductId.add(item.getId()));
            // 遍历数据库中的产品

            if (CollectionUtils.isNotEmpty(productList) || CollectionUtils.isNotEmpty(list)){
                updateRollBackSmartData(corpid,list,productList);
            }

            // 移除掉备份表中的产品
            productList.removeIf(item->backupProductId.contains(item.getId()));

            if (CollectionsUtil.isNotEmpty(productList)) {
                contractProductModel.deleteByIdIn(productList, corpid);
            }

            if (CollectionsUtil.isNotEmpty(list)) {
                contractProductModel.updateMulti(list, corpid);
            }


        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowContractStrategy.saveProduct error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 保存团队
     * @param list
     * @param corpid
     * @param dataId
     * @throws XbbException
     */
    private void saveUserTeam(List<ContractUserEntity> list, String corpid, Long dataId) throws XbbException {

        try {
            List<ContractUserEntity> contractUserList = contractUserModel.getContractUserList(corpid, dataId, null);
            List<Long> idList = new ArrayList<>();
            list.forEach(item->idList.add(item.getId()));

            contractUserList.removeIf(item->idList.contains(item.getId()));
            if (CollectionsUtil.isNotEmpty(contractUserList)) {
                contractUserModel.deleteBatchUser(contractUserList, corpid , DelEnum.DELETE.getDel());
            }
            if (CollectionsUtil.isNotEmpty(list)) {
                contractUserModel.updateBatch(list, corpid);
            }


        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowContractStrategy.saveUserTeam error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * @Author: wujian
     * @Description: 编辑进审批拒绝或者撤回时 回退以销定购采及智能补货数据
     * @Date: 下午2:24 2022/4/8
     * @Param: [corpid, beforeList:编辑前的关联产品, afterList:编辑后的关联产品]
     * @return: void
     **/
    private void updateRollBackSmartData(String corpid,List<ContractProductEntity> beforeList,List<ContractProductEntity> afterList) throws XbbException {
        // 移除编辑时新增的产品
        List<Long> beforeIdList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(beforeIdList)){
            beforeList.forEach(item -> beforeIdList.add(item.getId()));
        }
        // 采购结存表需要移除的产品
        List<String> delOnlyKeyList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(afterList)){
            for (ContractProductEntity contractProductEntity : afterList) {
                Long id = contractProductEntity.getId();
                if (!beforeIdList.contains(id)){
                    String onlyKey = id + "_" + contractProductEntity.getProductId();
                    delOnlyKeyList.add(onlyKey);
                }
            }
            if (CollectionUtils.isNotEmpty(delOnlyKeyList)){
                try {
                    purchaseBalanceModel.batchUpdateDel(corpid,delOnlyKeyList,1);
                }catch (Exception e){
                    log.error("WorkflowContractStrategy.saveProduct() 更新智能补货表数据时出错", e);
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
            }
        }
        // 回退智能补货数据
        Set<Long> productIdSet = new HashSet<>();
        Map<Long,Double> beforeNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,Double> afterNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionUtils.isNotEmpty(beforeList)){
            for (ContractProductEntity contractProductEntity : beforeList) {
                Long productId = contractProductEntity.getProductId();
                Double productNum = contractProductEntity.getProductNum();
                if (beforeNumMap.containsKey(productId)){
                    beforeNumMap.put(productId,Arith.add(beforeNumMap.get(productId),productNum));
                }else {
                    beforeNumMap.put(productId,productNum);
                }
                productIdSet.add(productId);
            }
        }
        if (CollectionUtils.isNotEmpty(afterList)){
            for (ContractProductEntity contractProductEntity : afterList) {
                Long productId = contractProductEntity.getProductId();
                Double productNum = contractProductEntity.getProductNum();
                if (afterNumMap.containsKey(productId)){
                    afterNumMap.put(productId,Arith.add(afterNumMap.get(productId),productNum));
                }else {
                    afterNumMap.put(productId,productNum);
                }
                productIdSet.add(productId);
            }
        }
        List<Long> productIdList = new ArrayList<>(productIdSet);
        // 产品的改变量 用于回退智能补货数据
        Map<Long,Double> changeNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionUtils.isNotEmpty(productIdList)){
            for (Long productId : productIdList) {
                Double beforeNum = beforeNumMap.getOrDefault(productId, 0D);
                Double afterNum = afterNumMap.getOrDefault(productId, 0D);
                // 改变量 = 改变之后的 - 改变之前的
                changeNumMap.put(productId,Arith.sub(afterNum,beforeNum));
            }
            // 查询除智能补货数据
            List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid, productIdList);
            if (CollectionUtils.isNotEmpty(smartReplenishmentEntityList)){
                for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                    Long productId = smartReplenishmentEntity.getProductId();
                    Double waitOutstockNum = smartReplenishmentEntity.getWaitOutstockNum();
                    Double changeNum = changeNumMap.getOrDefault(productId, 0D);
                    smartReplenishmentEntity.setWaitOutstockNum(Arith.sub(smartReplenishmentEntity.getWaitOutstockNum(), changeNum));
                }
                try {
                    smartReplenishmentModel.updateBatch(smartReplenishmentEntityList,corpid);
                }catch (Exception e){
                    log.error("WorkflowContractStrategy.saveProduct() 更新智能补货表数据时出错", e);
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
            }
        }
    }

    /**
     * @Author: wujian
     * @Description: 新建进审批拒绝回退以销定购智能补货数据
     * @Date: 下午2:57 2022/4/8
     * @Param: [corpid, productList]
     * @return: void
     **/
    private void addRollBackSmartData(String corpid,List<ContractProductEntity> productList) throws XbbException {
        // 工作流拒绝 回退智能补货数据
        Set<Long> productIdSet = new HashSet<>();
        Map<Long,Double> smartNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> onlyKeyList = new ArrayList<>();
        for (ContractProductEntity contractProductEntity : productList) {
            Long productId = contractProductEntity.getProductId();
            Double productNum = contractProductEntity.getProductNum();
            onlyKeyList.add(contractProductEntity.getId() + "_" + productId);
            if (smartNumMap.containsKey(productId)){
                smartNumMap.put(productId, Arith.add(smartNumMap.get(productId),productNum));
            }else {
                smartNumMap.put(productId,productNum);
            }
            productIdSet.add(productId);
        }
        List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid, new ArrayList<>(productIdSet));
        if(CollectionsUtil.isNotEmpty(smartReplenishmentEntityList)){
            for (SmartReplenishmentEntity entity : smartReplenishmentEntityList) {
                Long productId = entity.getProductId();
                if(smartNumMap.containsKey(productId)){
                    entity.setWaitOutstockNum(Arith.sub(entity.getWaitOutstockNum(), smartNumMap.get(productId)));
                }
            }
            try {
                smartReplenishmentModel.updateBatch(smartReplenishmentEntityList,corpid);
            }catch (Exception e){
                log.error("WorkflowContractStrategy.approvalFailed() 更新智能补货表数据时出错", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        try {
            // 更新结存表del
            purchaseBalanceModel.batchUpdateDel(corpid,onlyKeyList,DelEnum.DELETE.getDel());
        }catch (Exception e){
            log.error("WorkflowContractStrategy.approvalFailed() 更新以销定购表数据时出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

    }

}
